package com.olive.config;


import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import com.olive.filter.CaptchaCodeFilter;
import com.olive.handler.CommonLoginFailureHandler;
import com.olive.handler.CommonLoginSuccessHandler;
import com.olive.handler.MyLogoutSuccessHandler;
import com.olive.service.impl.UserDetailsServiceImpl;

@EnableWebSecurity
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
	
	@Autowired
	private UserDetailsServiceImpl commonUserDetailServiceImpl;
	@Autowired
	private CommonLoginSuccessHandler successHandler;
	@Autowired
	private CommonLoginFailureHandler failureHandler;
	@Autowired
	private MyLogoutSuccessHandler logoutSuccessHandler;
	@Autowired
	private CaptchaCodeFilter captchaCodeFilter;
	@Resource
	private SmsCodeSecurityConfig smsCodeSecurityConfig;

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.cors().and()
//				.addFilterBefore(captchaCodeFilter, UsernamePasswordAuthenticationFilter.class)
				.logout()
				.logoutSuccessHandler(logoutSuccessHandler)
				.and()
				.rememberMe()
				//默认都为remember-me
				.rememberMeParameter("remeber-me")
				//cookieName一般设置复杂一些，迷惑别人(不容易看出)
				.rememberMeCookieName("remeber-me")
				//过期时间
				.tokenValiditySeconds(24 * 60 * 60 * 2)
				.and()
				.csrf().disable()
				.formLogin()
				.loginPage("/toLogin") //用户没有权限就跳转到这个页面
				.loginProcessingUrl("/login")//登录跳转页面，表单中的action
				.usernameParameter("uname")
				.passwordParameter("upassword")//传递的属性
				.successHandler(successHandler)
				.failureHandler(failureHandler)
				.and()
				.apply(smsCodeSecurityConfig)
				.and().httpBasic().and()
				.authorizeRequests()
				.antMatchers("/home","/toLogin","/login", "/user/create", "/kaptcha", "/smsCode",
						"/smslogin").permitAll()
				.mvcMatchers("/test/a/*", "/oauth2/client/create").permitAll()
				.anyRequest().authenticated()
				.and()
				.sessionManagement()
				.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
				.sessionFixation().migrateSession()
				.maximumSessions(1).
				maxSessionsPreventsLogin(false)
				.expiredSessionStrategy(new CustomExpiredSessionStrategy());
	}


	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(commonUserDetailServiceImpl)
				.passwordEncoder(passwordEncoder());
	}

	@Override
	public void configure(WebSecurity web) {
		//将项目中的静态资源路径开放出来
		//为什么要抽出来？上面的规则都需要通过过滤器校验，这个不需要
		web.ignoring().antMatchers("/css/**", "/fonts/**", "/js/**", "/templates/**", "/static/**");
	}

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	//跨域配置
	@Bean
	CorsConfigurationSource corsConfigurationSource() {
		CorsConfiguration configuration = new CorsConfiguration();
		configuration.addAllowedOrigin("*");
		configuration.addAllowedMethod("*");
		configuration.addAllowedHeader("*");
		configuration.applyPermitDefaultValues();
		configuration.setAllowCredentials(true);
		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		source.registerCorsConfiguration("/**", configuration);
		return source;
	}
	
	@Bean
	@Override
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}
}

